class GameEntityData implements HashMap<String, Dynamic> {
  final GameEntity entity;
  final HashMap<String, Dynamic> m;
  
  GameEntityData(GameEntity e) : entity = e, m = new HashMap<String, Dynamic>() { }
  GameEntityData.from(GameEntity e, Map other) : entity = e, m = new HashMap<String, Dynamic>.from(other) {
    final w = world;
    m.forEach((k, v) => w._onDataAdded(entity, k));
  }

  Dynamic operator [](String key) => m[key];
  void operator []=(String key, Dynamic value) {
    if (value == null) {
      remove(key);
      return;
    }
    
    final newData = !m.containsKey(key);
    
    m[key] = value;
    
    if (newData)
      world._onDataAdded(entity, key);
  }
  
  void clear() {
    final w = world;
    m.forEach((k, v) => w._onDataRemoved(entity, k));
    m.clear();
  }
  
  bool containsKey(String key) => m.containsKey(key);
  bool containsValue(Dynamic value) => m.containsValue(value);
  void forEach(void f(String key, Dynamic value)) => m.forEach(f);
  Collection getKeys() => m.getKeys();
  Collection getValues() => m.getValues();
  bool isEmpty() => m.isEmpty();
  int get length() => m.length;
  
  Dynamic putIfAbsent(key, Dynamic ifAbsent()) {
    if (!m.containsKey(key)) {
      final value = ifAbsent();
      m[key] = value;
      world._onDataAdded(entity, key);
    } else
      return m[key];
  }
  
  Dynamic remove(key) {
    final value = m.remove(key);
    if (value != null)
      world._onDataRemoved(entity, key);
    
    return value;
  }
  
  String toString() => m.toString();
}